package main;

import java.io.FileWriter;
import java.io.IOException;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Stack;
import java.util.Vector;

import automata.Label;

import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;

import main.constraint.ConstraintAbstract;

/**
 * @author abrao
 */

public class LocalVal extends DefaultHandler
{
		
	private String xml; 
	private String chVal; 
	
	private Configuration conf1;
	private ConfigurationSet confSet1;
	private ConfigurationSet confSetAux = new ConfigurationSet();
	
	private Vector<ConfigurationSet> confVec = new Vector<ConfigurationSet>();
	private Vector<SyntAttributes> syntVec = new Vector<SyntAttributes>();	
	
	private KeysExecution ke = new KeysExecution();
	
	private Stack<Vector<ConfigurationSet>> stackConf = new Stack<Vector<ConfigurationSet>>();
	private Stack<Vector<SyntAttributes>> stackSynt = new Stack<Vector<SyntAttributes>>();
	private Stack stackKeyTree = new Stack();
	
	private StringBuffer posSt = new StringBuffer();
	private int pos = 0;
	private int posRight = 0;
	private ArrayList lval = new ArrayList();
	private int counter = 0;
	
	public Vector htVec;
	public Vector<Hashtable<String,ArrayList<Inters>>> interVec;
	  
	public LocalVal()
	{
		xml = new String();		
	}
	
	public Vector<SyntAttributes> localParseVal (String localTree, KeysExecution kexec, 
	                        	 				 Vector<ConfigurationSet> confArg, StringBuffer posAnt)
	{
	   FileWriter localXML;
	   try
	   {
	   	   localXML = new FileWriter("localVal.xml") ;
		   localXML.write(localTree);
		   localXML.close();
	   }
	   catch (IOException e)
	   {
		   System.out.print("Error: file opening");
	   };
	   
	   int j = posAnt.lastIndexOf(".");
	   posRight = Integer.valueOf(posAnt.substring(j+1)).intValue();	
	   posAnt.substring(0,j);
	   posSt = posAnt;
	 
	   SAXParser splocal = new SAXParser();
	   ke = kexec;
	   InputSource source = new InputSource("localVal.xml");
	   splocal.setContentHandler(this);
        		
	   // List of the keys being verified	
	   ArrayList<ConstraintAbstract> hsKeys = ke.getKeysSet();
       
	   htVec = new Vector();
	   interVec = new Vector<Hashtable<String,ArrayList<Inters>>>();
	   
	   int numKeys=hsKeys.size();
	   for (int i=0; i<numKeys; i++)
	   {
		   SyntAttributes syntAtt = new SyntAttributes();	
		   syntVec.add(syntAtt);
		   				
		   Hashtable htContextXfd = new Hashtable();
		   htVec.add(htContextXfd);
		   Hashtable<String,ArrayList<Inters>> htIntersXfd = new Hashtable<String,ArrayList<Inters>>();
		   interVec.add(htIntersXfd);
	   }
	     	
	   // Stacks CONF and SYNT to inherited and synthesized attributes respectively.
	   stackConf.add(confArg);
	   stackSynt.add(syntVec);
	   
	   try
	   {
		   splocal.parse(source);
		   syntVec = (Vector) stackSynt.lastElement();
		   return (syntVec);
	   }
	   catch (Exception e)
	   {
		   System.out.println("Parse Error: "+e);
	   }
	   
	   return (new Vector());
	}

		
	public void startDocument()
	{
		xml = "<?xml version =\"1.0\"?>\n";
	}
	
	public void startElement(String namespaceURI, String localName,
			String rawName, Attributes attrs)
	{
		chVal = new String();
		confSetAux = new ConfigurationSet();
		Label l = new Label(rawName);
		Vector<SyntAttributes> vecSynt = new Vector<SyntAttributes>();
		ArrayList data = new ArrayList();

		// List of the constraints being verified
		ArrayList<ConstraintAbstract> keyList = ke.getKeysSet();
		for (Iterator<ConstraintAbstract> i = keyList.iterator(); i.hasNext();)
		{
			i.next();
			SyntAttributes syntAtt = new SyntAttributes();
	        syntAtt.setNodeName(rawName);
			vecSynt.add(syntAtt);
		}

		posSt.append(".");
		posSt.append(posRight);
		posRight = 0;

		confVec = (Vector<ConfigurationSet>) stackConf.lastElement();
		Vector<ConfigurationSet> vecAux = new Vector<ConfigurationSet>();
		
		for (Iterator<ConfigurationSet> i = confVec.iterator(); i.hasNext();)//for all constraints do:
		{
			confSet1 = (ConfigurationSet) i.next();
			confSetAux = confSet1.changeConfiguration(l);
			
			vecAux.add(confSetAux);
		}
		
		stackConf.push(vecAux);
		stackSynt.push(vecSynt);

		//attributes are already leaves, so they are treated here
		int len = attrs.getLength();
		if (len > 0)//A->data
		{
			data.clear();
			for (int i = 0; i < len; i++)
			{
				//StringBuffer posAt = posSt;
				posSt.append(".");
				posSt.append(posRight);
				posRight++;
				String sa = attrs.getQName(i);
				String sb = (String) attrs.getValue(i);
				
				int j = posSt.lastIndexOf(".");
				//posSt.substring(0,j);
				
				Label la = new Label(sa);
				vecSynt = (Vector<SyntAttributes>) stackSynt.pop();
				confVec = (Vector<ConfigurationSet>) stackConf.peek();
				
				for (int k = 0; k < confVec.size(); k++)//for all keys do:
				{
					Hashtable<String,ArrayList<Inters>> htIntersXfd = interVec.elementAt(k);
					confSet1 = (ConfigurationSet) confVec.elementAt(k);
					confSetAux = confSet1.changeConfiguration(la); //alteracao
					confSetAux.keyValidationData(vecSynt, k, sb, posSt.substring(0,j), posSt.toString(), rawName,htIntersXfd);
				}
				
				stackSynt.push(vecSynt);
				posSt.delete(j,posSt.length());
			}
		}
	}

	public void characters(char ch[], int start, int length)
	{
		String str = new String(ch, start, length);
		str = str.trim();
		chVal += str;
	}
	
	public void endElement(String namespaceURI, String localName, String rawName)
	{
		/* First part: to treat the chVal (that contains the data value between
		 * open and close tags
		 * Data values are enclosed in the respective structures, for all constraints
		 * and are stored in the stacks
		 */
		System.out.println("LV: closing node:"+rawName);
		Vector<SyntAttributes> vecSyntAnt = new Vector<SyntAttributes>();
		
		ArrayList al = (ArrayList) ke.getKeysSet();
		Vector vecSynt = new Vector();
		
		
		//StringBuffer posAt = posSt;
		int j = posSt.lastIndexOf(".");
		posRight = Integer.valueOf(posSt.substring(j+1)).intValue();		
		posRight++;
		//posSt.substring(0,j);
		
		
		if(!chVal.isEmpty())//A->data
		{			
			confVec = (Vector<ConfigurationSet>) stackConf.pop();//lastElement();
			vecSynt = (Vector) stackSynt.pop();
			vecSyntAnt = (Vector<SyntAttributes>) stackSynt.pop();
			
			for (int k = 0; k < confVec.size(); k++)//for all keys do:
			{
				confSet1 = (ConfigurationSet) confVec.elementAt(k);
				Hashtable<String,ArrayList<Inters>> htIntersXfd = interVec.elementAt(k);
				vecSyntAnt = confSet1.keyValidationData(vecSyntAnt, k, chVal, posSt.substring(0,j), posSt.toString(), rawName, htIntersXfd);
			}		
			
			stackSynt.push(vecSyntAnt);
		}		
		else//A->a1,...,an
		{
			// Extraction of values that are at the bottom of the stacks
			confVec = (Vector<ConfigurationSet>) stackConf.pop();
			
			int k;

			vecSynt = (Vector) stackSynt.pop();	
			vecSyntAnt = (Vector<SyntAttributes>) stackSynt.pop();
			
			for (k = 0; k < confVec.size(); k++)// for each constraint : appropriate validation
			{
				confSet1 = (ConfigurationSet) confVec.elementAt(k);
				Hashtable htContextXfd = (Hashtable) htVec.elementAt(k);
				Hashtable<String,ArrayList<Inters>> htIntersXfd = interVec.elementAt(k);
				SyntAttributes stH = (SyntAttributes)vecSynt.elementAt(k);
				//attention: checks null values, is error hashtable
		    	vecSyntAnt = confSet1.keyValidationInNode(vecSyntAnt, k, stH, posSt.substring(0,j), posSt.toString(), rawName, htContextXfd, htIntersXfd, null);
			}
			
			posSt = posSt.delete(j,posSt.length());
			//System.out.println("Vetor HT:" +htVec.toString());
			stackSynt.push(vecSyntAnt);				
		}	
		
		chVal = new String();
	}

    public String getResult()
    {
    	return (htVec.toString());
    }
  
	public KeysExecution getKeysExecution()
	{
		return ke;
	}  
	  
	public void setKeysExecution(KeysExecution keArg)
	{
		ke = keArg;
	}   

    public String removeWhite(String s)
    {
    	int i=0;
    	while (s.startsWith(" "))
    		 s = s.substring(i+1,s.length());
        while (s.endsWith(" "))
             s = s.substring(i,s.length()-1);
        
        return s;
    }
}
